#include "factory.h"


int trans_file(ptaskNode_t ptask)
{
    train_t dataTrain;

    //发送文件大小
    struct stat statbuf;
    stat(ptask->fileName,&statbuf);
    dataTrain.dataLen = sizeof(off_t);
    memcpy(dataTrain.buf,&statbuf.st_size,dataTrain.dataLen);
    send(ptask->fd,&dataTrain,4+dataTrain.dataLen,0);
    //发送文件的内容
    //在改进版本的server里，
    //对发送文件内容的方式做出改进，
    //利用mmap 的DMA技术，直接
    int fd = open(ptask->fileName,O_RDWR);//使用mmap时，记得把这改成可读可写，否则可能会有权限问题
    ERROR_CHECK(fd,-1,"open");
    char *pmap = (char *)mmap(NULL,statbuf.st_size,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
    ERROR_CHECK(pmap,(char *)-1,"mmap in trans_file");
    send(ptask->fd,pmap,statbuf.st_size,0);//这里注意理解mmap 的 零拷贝！
    
    return 0;
}

int recv_file(ptaskNode_t ptask)
{
    //接收文件大小，
    int dataLen = 0;
    off_t fileLen = 0;
    recvCyc(ptask->fd,&dataLen,sizeof(int));
    recvCyc(ptask->fd,&fileLen,dataLen);
    printf("recv fileLen: %ld\n",fileLen);
    //mmap

    //创建非重名文件
    char downloadPath[512];
    strcpy(downloadPath, ptask->fileName);
    int fd = 0;
    int i = 1;
    int buflen = strlen(ptask->fileName);
    int tmp = 0;
    while(-1 == (fd = open(downloadPath,O_RDWR|O_CREAT|O_EXCL,0666)))
    {
        tmp = buflen;
        while(downloadPath[tmp])
        {
            downloadPath[tmp++] = 0;
        }
        sprintf(downloadPath,"%s%d",downloadPath,i++);
    }

    printf("Receiving file...name :%s ,size : %ld M\n",ptask->fileName,fileLen/(1024*1024));

    ftruncate(fd,fileLen);
    char *pmap = (char *)mmap(NULL,fileLen,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
    if(pmap == (char*)-1)
    {
        fprintf(stderr, "err in gets :pmap failed\n");
    }
    int ret = recvCyc(ptask->fd,pmap,fileLen);
    if(!ret)
    {
        printf("download success\n");
    }
    else
    {
        printf("download failed!\n");
    }
    munmap(pmap,fileLen);
}

int recvCyc(int socketfd,void *buf,size_t len)
{
    char *p = (char *)buf;//因为后边recv有指针的加操作，所以这里指针的基类型要转换成char*！
    unsigned long total = 0;
    int ret;
    while(total != len)
    {
        ret = recv(socketfd,p+total,len - total,0);//这里注意第二个参数是p+total！！！也就是接着上一次的地方往后写！！不然就错了！
        ERROR_CHECK(ret,-1,"recv in recvCycle");
        total+=ret;
    }
    return 0;
}
